import { klona } from 'klona';
import Decimal from 'decimal.js';

/**
 * @desc 随机数生成
 * @param {number} min 最小数
 * @param {number} max 最大数
 * @return {number}
 */
function randomNumber(min, max) {
	return Math.round(Math.random() * (max - min)) + min;
}

/***
 * @desc 小于10加0
 * @param {number} num 数字
 * @returns {string}
 */
function formatTen(num) {
	return num > 9 ? num + "" : "0" + num;
}

/**
 * @desc 延时
 * @param time {number} 延时时间
 * @return {Promise}
 */
function sleep(time) {
	return new Promise(function(resolve) {
		setTimeout(function() {
			resolve("");
		}, time);
	});
}

/**
 * @desc 格式化日期
 * @param {Date} date 日期
 * @param {string} fmt 日期格式
 * @returns {String}
 */
function formatDate(date, fmt = "yyyy-mm-dd hh:MM:ss") {
	if (!uni.$uv.test.date(date)) return "";

	date = new Date(date);
	const year = date.getFullYear().toString();
	const month = formatTen(date.getMonth() + 1);
	const day = formatTen(date.getDate());
	const hh = formatTen(date.getHours());
	const mm = formatTen(date.getMinutes());
	const ss = formatTen(date.getSeconds());

	return fmt.replace(/yyyy/g, year).replace(/mm/g, month).replace(/dd/g, day).replace(/hh/g, hh).replace(/MM/g, mm).replace(/ss/g, ss);
}

/**
 * @desc 日期简写
 * @param {Date} date 日期
 * @returns {string}
 */
function shortDate(date) {
	const inputDate = new Date(date);
	const inputTime = inputDate.getTime() / 1000;
	const currentTime = parseInt(Date.now() / 1000);
	const diffTime = currentTime - inputTime;

	if (uni.$uv.test.number(diffTime)) {
		if (diffTime < 60 * 10) {
			return "刚刚";
		} else if (diffTime < 60 * 60) {
			return `${Math.floor(diffTime / 60)}分钟前`;
		} else if (diffTime < 60 * 60 * 24) {
			return `${Math.floor(diffTime / 3600)}小时前`;
		} else if (diffTime < 60 * 60 * 24 * 4) {
			return `${Math.floor(diffTime / (60 * 60 * 24))}天前`;
		} else if (diffTime < 60 * 60 * 24 * 365) {
			return `${inputDate.getMonth() + 1}月${inputDate.getDate()}日`;
		} else {
			return `${inputDate.getFullYear()}年${inputDate.getMonth() + 1}月${inputDate.getDate()}日`;
		}
	}
}

/**
 * @desc 深度拷贝
 * @param {Array|Object} data 数据
 * @return {Array|Object} 
 */
function deepCopy(data) {
	const newData = klona(data);
	return newData;
}

/**
 * @desc 加载和请求loading
 * @desc {string} type 类型
 * @param {boolean} mask 遮罩
 * @return {null}
 */
function loading(type = 'req', mask = true) {
	let title = '';
	switch (type) {
		case 'req':
			title = '请求中...'
			break;
		case 'page':
			title = '加载中...'
			break;
		default:
			title = '请求中...'
	}

	uni.showLoading({ title, mask });
}

/**
 * @desc 提示
 * @param {String} title 提示
 * @param {String} icon 图标
 * @param {Number} duration 延迟时间
 * @param {Function} fun 要执行的回调函数
 */
function toast({ title, icon = 'none', duration = 2000, fun }) {
	// #ifdef MP-TOUTIAO
	icon === 'error' && (icon = 'fail')
	// #endif
	uni.showToast({
		title,
		icon,
		duration,
		success: () => {
			setTimeout(() => {
				uni.$uv.test.func(fun) && fun();
			}, duration)
		}
	});
}

/**
 * @desc 获取页面栈
 * @param {Number} preIndex为1时获取上一页
 * @return {Object} 
 */
function prePage(preIndex = 0) {
	const pages = getCurrentPages();
	return pages[pages.length - (preIndex + 1)] || {};
}

/**
 * @desc 获取小程序登录Code
 * @return {Promise[Object]} 
 */
function getLoginCode() {
	return new Promise(resolve => {
		uni.getProvider({
			service: 'oauth',
			success: ({ provider }) => {
				uni.login({
					provider: provider[0],
					success: ({ code }) => {
						resolve({ code: 200, data: code })
					},
					fail: (err) => {
						resolve({ code: 210, err: '获取Code失败' })
					}
				})
			},
			fail: (err) => {
				resolve({ code: 210, err: '获取Code失败' })
			}
		})
	})
}

/**  
 * @desc 将数字格式化为更易读的格式
 * @param {number} num - 需要格式化的数字。  
 * @returns {string} - 格式化后的字符串。  
 */
function formatNumber(num) {
	if (num >= 10000) {
		return (num / 10000).toFixed(1) + '万';
	}
	return (num || 0).toString();
}

/**
 * @desc 获取元素信息
 * @return Object
 */
function getRect(selector) {
	return new Promise((resolve) => {
		let view = uni.createSelectorQuery().select(selector);
		view.fields({ size: true, rect: true, scrollOffset: true }, (res) => {
			resolve(res);
		}).exec();
	})
}

/**
 * @desc 分转元
 * @param {Number} cent 金额（分）
 * @return {Number} 金额（元）
 */
function convertCentToYuan(cent) {
	if (uni.$uv.test.number(cent)) {
		return new Decimal(cent).dividedBy(100).toNumber();
	}
	return 0;
}

/**
 * @desc 表单赋值
 * @param {Object} formData 表单数据
 * @param {Object} data 赋值数据
 */
function formAssign(formData, data = {}) {
	for (const key of Object.keys(formData)) {
		if (key === 'id' && data['_id']) {
			formData['id'] = data['_id'];
		} else if (data[key]) {
			formData[key] = data[key];
		}
	}
}


export default {
	randomNumber,
	formatTen,
	sleep,
	formatDate,
	shortDate,
	deepCopy,
	loading,
	toast,
	prePage,
	getLoginCode,
	formatNumber,
	getRect,
	convertCentToYuan,
	formAssign
}